package org.surelink.radius.console;


import de.tototec.cmdoption.CmdOption;
import de.tototec.cmdoption.CmdlineParser;
import org.surelink.radius.console.message.Request;
import org.surelink.radius.console.message.RespBase;
import org.surelink.radius.console.message.Response;
import org.tinyradius.dictionary.AttributeType;
import org.tinyradius.dictionary.DefaultDictionary;
import org.tinyradius.packet.AccessRequest;
import org.tinyradius.packet.AccountingRequest;
import org.tinyradius.packet.RadiusPacket;
import org.tinyradius.util.RadiusClient;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

public class RadiusProcess extends BaseProcess{

    class Config{
        @CmdOption(names = {"--help"}, description = "打印帮助",isHelp = true)
        private boolean help;

        @CmdOption(names = {"radius"} ,hidden = true)
        private boolean radius;


        @CmdOption(names = {"auth"} ,description = "用户认证测试")
        private boolean auth;

        @CmdOption(names = {"acct"} ,description = "用户记账测试")
        private boolean acct;

        @CmdOption(names = {"--accttype", "-t"},args={"accttype"}, minCount = -1,maxCount = 1,description = "记账类型:start/update/stop/on/off")
        String type;

        @CmdOption(names = {"--username", "-u"},args={"userName"}, minCount = -1,maxCount = 1,description = "用户上网账号")
        String username;

        @CmdOption(names = {"--password", "-p"},args={"password"}, minCount = -1,maxCount = 1,description = "用户上网密码")
        String password;

        @CmdOption(names = {"--secret","-s"},args={"secret"}, minCount = -1,maxCount = 1,description = "客户端共享密钥")
        String secret;

        @CmdOption(names = {"--sessionid","-sid"},args={"sessionid"}, minCount = -1,maxCount = 1,description = "会话id")
        String sessionid = "123456789";

        @CmdOption(names = {"--encry","-e"},args={"encry"}, minCount = -1,maxCount = 1,description = "密码加密类型：pap/chap")
        String encry = "pap";

        @CmdOption(names = {"--attrs", "-a"}, args = {"attrName", "attrValue"}, minCount = -1,maxCount = -1,
                description = "属性： 属性名称 属性值")
        final Map<String, String> attrs = new LinkedHashMap<String, String>();

    }

    public  RadiusProcess(){
        setOperate("radius");
    }

    @Override
    public Response process(Request req) throws Exception {
        Config config = new Config();
        CmdlineParser cp = new CmdlineParser(config);
        cp.setProgramName(getOperate());
        cp.parse(req.getCommand().split("\\s+"));

        if(config.help)
        {
            StringBuilder sb = new StringBuilder();
            cp.usage(sb);
            return new Response(RespBase.SUCCESS.getCode(),sb.toString());
        }

        if(config.auth){
            RadiusClient rc = new RadiusClient("127.0.0.1", config.secret);
            AccessRequest request = new AccessRequest(config.username, config.password);
            request.addAttribute("NAS-Identifier", "surelink-tester");
            request.addAttribute("NAS-IP-Address", "127.0.0.1");
            request.setAuthProtocol(config.encry);

            for (Iterator<Map.Entry<String, String>> iterator = config.attrs.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry<String, String> ent = iterator.next();
                AttributeType attrType = DefaultDictionary.getDefaultDictionary().getAttributeTypeByName(ent.getKey());
                if (attrType != null) {
                    request.removeAttributes(attrType.getTypeCode());
                    request.addAttribute(ent.getKey().trim(), ent.getValue());
                }
            }
            RadiusPacket response = rc.authenticate(request);
            return new Response(response);
        }
        else if(config.acct){
            RadiusClient rc = new RadiusClient("127.0.0.1", config.secret);
            AccountingRequest request = new AccountingRequest(config.username, getAcctType(config.type));
            request.addAttribute("Acct-Session-Id", config.sessionid);
            request.addAttribute("NAS-IP-Address", "127.0.0.1");
            request.addAttribute("NAS-Identifier", "surelink-tester");
            request.addAttribute("NAS-Port", "0");
            for (Iterator<Map.Entry<String, String>> iterator = config.attrs.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry<String, String> ent = iterator.next();
                AttributeType attrType = DefaultDictionary.getDefaultDictionary().getAttributeTypeByName(ent.getKey());
                if (attrType != null) {
                    request.removeAttributes(attrType.getTypeCode());
                    request.addAttribute(ent.getKey().trim(), ent.getValue());
                }
            }
            RadiusPacket response = rc.account(request);
            return new Response(response);
        }

        StringBuilder sb = new StringBuilder();
        cp.usage(sb);
        return RespBase.MSG_FORMAT_ERR;
    }


    private int getAcctType(String type){

        if("start".equals(type))
        {
            return  AccountingRequest.ACCT_STATUS_TYPE_START;
        }
        else if("update".equals(type))
        {
            return  AccountingRequest.ACCT_STATUS_TYPE_INTERIM_UPDATE;
        }
        else if("stop".equals(type))
        {
            return  AccountingRequest.ACCT_STATUS_TYPE_STOP;
        }
        else if("on".equals(type))
        {
            return  AccountingRequest.ACCT_STATUS_TYPE_ACCOUNTING_ON;
        }
        else if("off".equals(type))
        {
            return  AccountingRequest.ACCT_STATUS_TYPE_ACCOUNTING_OFF;
        }
        else
        {
            return  AccountingRequest.ACCT_STATUS_TYPE_START;
        }

    }
}
